<?php

namespace app\land\controller;

use app\land\utils\JsonResponse;
use support\Redis;

class IndexController
{
    use JsonResponse;

    /**
     * key名称
     * @param $landId
     * @return string[]
     * @author: Colin<amcolin@126.com>
     * @datetime: 2023/10/17 16:19
     */
    protected static function getKeyName($landId){
        // 初始化这个落地页的redis-key名
        $day = date('Ymd');
        $landDay = $day . '_' . $landId;
        // 落地页信息的key
        $todayKeyName = 'land_stat_' . $day;
        // uv的key
        $uvKeyName = 'land_uv_' . $landDay;
        // pv的key
        $pvKeyName = 'land_pv_' . $landDay;
        // 上报的key
        $reportKeyName = 'land_report_' . $landDay;
        // 用户的事件统计
        $uvEventName = 'land_event_' . $landDay;
        // 用户的clickId和类型组合的数据
        $clickType = 'land_click_type' . $landDay;
        $prefix = 'laravel_database_';
        $names = [
            'todayKeyName' => $todayKeyName ,
            'uvKeyName' => $uvKeyName ,
            'pvKeyName' => $pvKeyName ,
            'reportKeyName' => $reportKeyName ,
            'uvEventName' => $uvEventName ,
            'clickType' => $clickType ,
        ];
        foreach ($names as &$val){
            $val = $prefix . $val;
        }
        return $names;
    }

    /**
     * 今天还剩多少秒
     * @return false|int
     * @author: Colin<amcolin@126.com>
     * @datetime: 2023/10/17 16:18
     */
    protected function getTodaySecond(){
        return strtotime('23:59:59') - time();
    }

    /**
     * 设置过期时间
     * @param $key
     * @param $second
     * @return void
     * @author: Colin<amcolin@126.com>
     * @datetime: 2023/10/17 16:22
     */
    protected function setExpire($key , $second){
        if (Redis::ttl($key) == -1 && $second > 0){
            Redis::expire($key , $second);
        }
    }

    /**
     * 设置过期时间为今天
     * @param $key
     * @return void
     * @author: Colin<amcolin@126.com>
     * @datetime: 2023/10/17 16:23
     */
    protected function setExpireToday($key){
        $this->setExpire($key , $this->getTodaySecond());
    }

    /**
     * 记录一个信息
     * @return \support\Response
     * @author: Colin<amcolin@126.com>
     * @datetime: 2023/10/17 15:19
     */
    public function record(){
        $landId = request()->post('id');
        if (!$landId){
            return $this->error('无效的落地页信息');
        }
        $type = request()->post('type');
        $clickId = request()->post('click_id');
        if (!$clickId){
            return $this->error('无效的clickId');
        }
        // 自定义信息
        $customer = request()->post('customer');
        if (!$customer){
            $customer = [];
        }
        $second = $this->getTodaySecond();
        // 初始化这个落地页的redis-key名
        $keys = self::getKeyName($landId);
        $todayKeyName = $keys['todayKeyName'];
        $uvKeyName = $keys['uvKeyName'];
        $pvKeyName = $keys['pvKeyName'];
        $reportKeyName = $keys['reportKeyName'];
        $uvEventName = $keys['uvEventName'];
        $clickType = $keys['clickType'];
        // 设置一下这个的信息
        $landInfo = Redis::hGet($todayKeyName, $landId);
        $landInfo = $landInfo ? json_decode($landInfo , true) : [];
        if ($type == 'open'){
            // 记录UV和PV
            Redis::sAdd($uvKeyName , $clickId);
            Redis::incr($pvKeyName);
            $landInfo['uv'] = Redis::sCard($uvKeyName);
            $landInfo['pv'] = Redis::get($pvKeyName);
            $this->setExpire($uvKeyName , $second);
            $this->setExpire($pvKeyName , $second);
        }
        // 处理这个事件数
        if (!isset($landInfo['event_counts'])) $landInfo['event_counts'] = [];
        if (!isset($landInfo['event_counts'][$type])) $landInfo['event_counts'][$type] = 0;
        $landInfo['event_counts'][$type] += 1;

        // 处理用户上报的事件，1个clickId 只记录1次
        if (!isset($landInfo['user_event_counts'])) $landInfo['user_event_counts'] = [];
        if (!isset($landInfo['user_event_counts'][$type])) $landInfo['user_event_counts'][$type] = 0;
        $memberKey = $clickId . '_' . $type;
        if (!Redis::sIsMember($clickType , $memberKey)){
            // 一个用户，只记录一次上报$type的数据
            $landInfo['user_event_counts'][$type] += 1;
            Redis::sAdd($clickType , $memberKey);
            $this->setExpire($clickType , $second);
        }

        // 统计这个用户的事件信息
        $clickData = Redis::hGet($uvEventName , $clickId);
        $clickData = $clickData ? json_decode($clickData , true) : [];
        if (!isset($clickData['events'])) $clickData['events'] = [];
        if (!isset($clickData['event_counts'])) $clickData['event_counts'] = [];
        if (!isset($clickData['event_counts'][$type])) $clickData['event_counts'][$type] = 0;
        $clickData['events'][] = $type;
        // 重新组装
        $events = array_merge(array_unique($clickData['events']));
        $clickData['event_counts'][$type] += 1;
        $clickData['events'] = $events;
        $clickData['update_time'] = time();
        // 组装结束，保存起来
        Redis::hSet($uvEventName , $clickId , json_encode($clickData));
        $this->setExpire($uvEventName , $second);
        // 保存落地页信息
        Redis::hSet($todayKeyName , $landId , json_encode($landInfo));
        $this->setExpire($todayKeyName , $second + 600); // 多保存10分钟，方便做数据和存储入库
        // 记录上报的数据
        Redis::rPush($reportKeyName , json_encode([
            'id' => $landId ,
            'event' => $type ,
            'customer' => $customer ,
            'click_id' => $clickId ,
            'report_time' => time() ,
        ]));
        $this->setExpire($reportKeyName , $second);
        return $this->success();
    }

//    public function showStat(){
//        $landId = request()->get('id');
//        $keys = self::getKeyName($landId);
//        $todayKeyName = $keys['todayKeyName'];
//        $reportKeyName = $keys['reportKeyName'];
//        $landInfo = Redis::hGet($todayKeyName , $landId);
//        $landInfo = $landInfo ? json_decode($landInfo , true) : [];
//        // 查看这个落地页的uv和pv
//        echo 'uv is ' . $landInfo['uv'] . PHP_EOL;
//        echo 'pv is ' . $landInfo['pv'] . PHP_EOL;
//        // 上报的事件列表
//        $list = Redis::lRange($reportKeyName , 0 , 1000);
//        foreach ($list as $val){
//            echo $val . PHP_EOL;
//        }
//    }
}